<template>
  <div class="indicator-page">
    <!-- 顶部操作栏 -->
    <div class="action-bar">
      <div class="action-left">
        <h1 class="page-title">📊 股票指标分析</h1>
      </div>
      <div class="action-right">
        <button 
          class="refresh-btn" 
          @click="refreshAllData" 
          :disabled="refreshLoading"
          :title="refreshLoading ? '正在修复数据...' : '修复所有数据（重新获取基础信息、K线数据、恐贪指数）'"
        >
          <span v-if="refreshLoading">🔄 修复中...</span>
          <span v-else>🔧 修复数据</span>
        </button>
      </div>
    </div>

    <!-- 顶部横向Tab -->
    <div class="tab-container">
      <div 
        v-for="(tab, index) in tabs" 
        :key="index"
        :class="['tab-item', { active: activeTab === index }]"
        @click="switchTab(index)"
      >
        {{ tab.name }}
      </div>
    </div>

    <!-- 我的自选 Tab -->
    <div v-if="activeTab === 0" class="tab-content">
      <div class="empty-state">
        <div class="empty-icon">📋</div>
        <div class="empty-text">我的自选</div>
        <div class="empty-desc">暂无自选股票</div>
      </div>
    </div>

    <!-- 美股杠杆 Tab -->
    <div v-if="activeTab === 1" class="tab-content">
      <div class="table-container">
        <table class="stock-table">
          <thead>
            <tr>
              <th @click="sortBy('code')" class="sortable-header">
                <div class="header-content">
                  <span>代码</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'code' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'code' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('name')" class="sortable-header">
                <div class="header-content">
                  <span>中文名称</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'name' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'name' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('fearGreedIndex')" class="sortable-header">
                <div class="header-content">
                  <span>恐贪指数</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'fearGreedIndex' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'fearGreedIndex' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('price')" class="sortable-header">
                <div class="header-content">
                  <span>市价</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'price' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'price' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="stock in sortedStocks" :key="stock.code" @click="selectStock(stock)">
              <td class="stock-code">{{ stock.code }}</td>
              <td class="stock-name">{{ stock.name }}</td>
              <td class="fear-greed-index">
                <span :class="getFearGreedClass(stock.fearGreedIndex)">
                  {{ stock.fearGreedIndex }}
                </span>
              </td>
              <td class="stock-price">{{ stock.price }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 美股常规 Tab -->
    <div v-if="activeTab === 2" class="tab-content">
      <div class="table-container">
        <table class="stock-table">
          <thead>
            <tr>
              <th @click="sortBy('code')" class="sortable-header">
                <div class="header-content">
                  <span>代码</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'code' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'code' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('name')" class="sortable-header">
                <div class="header-content">
                  <span>中文名称</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'name' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'name' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('fearGreedIndex')" class="sortable-header">
                <div class="header-content">
                  <span>恐贪指数</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'fearGreedIndex' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'fearGreedIndex' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('price')" class="sortable-header">
                <div class="header-content">
                  <span>市价</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'price' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'price' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="stock in sortedStocks" :key="stock.code" @click="selectStock(stock)">
              <td class="stock-code">{{ stock.code }}</td>
              <td class="stock-name">{{ stock.name }}</td>
              <td class="fear-greed-index">
                <span :class="getFearGreedClass(stock.fearGreedIndex)">
                  {{ stock.fearGreedIndex }}
                </span>
              </td>
              <td class="stock-price">{{ stock.price }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 美股个股 Tab -->
    <div v-if="activeTab === 3" class="tab-content">
      <div class="table-container">
        <table class="stock-table">
          <thead>
            <tr>
              <th @click="sortBy('code')" class="sortable-header">
                <div class="header-content">
                  <span>代码</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'code' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'code' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('name')" class="sortable-header">
                <div class="header-content">
                  <span>中文名称</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'name' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'name' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('fearGreedIndex')" class="sortable-header">
                <div class="header-content">
                  <span>恐贪指数</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'fearGreedIndex' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'fearGreedIndex' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
              <th @click="sortBy('price')" class="sortable-header">
                <div class="header-content">
                  <span>市价</span>
                  <div class="sort-indicator">
                    <span v-if="sortField === 'price' && sortOrder === 'asc'" class="sort-arrow">↑</span>
                    <span v-else-if="sortField === 'price' && sortOrder === 'desc'" class="sort-arrow">↓</span>
                    <span v-else class="sort-arrow">↕</span>
                  </div>
                </div>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="stock in sortedStocks" :key="stock.code" @click="selectStock(stock)">
              <td class="stock-code">{{ stock.code }}</td>
              <td class="stock-name">{{ stock.name }}</td>
              <td class="fear-greed-index">
                <span :class="getFearGreedClass(stock.fearGreedIndex)">
                  {{ stock.fearGreedIndex }}
                </span>
              </td>
              <td class="stock-price">{{ stock.price }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-overlay">
      <div class="loading-spinner"></div>
      <div class="loading-text">{{ loadingText }}</div>
    </div>

    <!-- 错误状态 -->
    <div v-if="error" class="error-overlay">
      <div class="error-icon">⚠️</div>
      <div class="error-text">{{ error }}</div>
      <button @click="retryLoad" class="retry-button">重试</button>
    </div>

    <!-- 服务状态指示器 -->
    <div v-if="showServiceStatus" class="service-status">
      <div class="service-indicator" :class="serviceStatus.status">
        <span class="status-dot"></span>
        <span class="status-text">{{ getServiceStatusText() }}</span>
      </div>
    </div>


  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()

// Tab配置
const tabs = [
  { name: '我的自选' },
  { name: '美股杠杆' },
  { name: '美股常规' },
  { name: '美股个股' }
]

// 股票代码数组 - 根据图片数据
const STOCK_CODES = {
  leverage: [ // 美股杠杆
    'GDXU.US', 'PTIR.US',
     'KORU.US', 'UGL.US', 'NVDL.US', 'AVGX.US', 'GGLL.US', 'UTSL.US', 'FBL.US', 'BULZ.US',
    'TQQQ.US', 'ETHU.US', 'TECL.US', 'SSO.US', 'MSFU.US', 'UPRO.US', 'SPXL.US', 'FNGU.US', 'DFEN.US', 'SPYU.US',
    // 'AMDL.US', 'WEBL.US', 'TSMX.US', 'EURL.US', 'BITX.US', 'RETL.US', 'AAPU.US', 'BRZU.US', 'BABX.US', 'YINN.US',
    // 'CWEB.US', 'FAS.US', 'CHAU.US', 'UDOW.US', 'NAIL.US', 'AMZU.US', 'SOXL.US', 'TNA.US', 'TSLL.US', 'CONL.US',
    // 'MSTU.US', 'DPST.US', 'LABU.US', 'CURE.US', 'SMCX.US', 'BRKU.US', 'TMF.US', 'UCO.US', 'OILU.US', 'INDL.US', 'BOIL.US'
  ],
  regular: [ // 美股常规
    'AGG.US', 'KWEB.US',
    //  'XLU.US', 'SPMO.US', 'VUG.US', 'QQQ.US', 'VOX.US', 'NLR.US', 'VTI.US', 'SPY.US',
    // 'SMH.US', 'VIG.US', 'XLC.US', 'XLP.US', 'VTV.US', 'VDC.US', 'IBIT.US', 'YMAX.US', 'ITB.US', 'XLI.US',
    // 'ARKK.US', 'DIA.US', 'XLF.US', 'IAK.US', 'IWM.US', 'KRE.US', 'XBI.US', 'XLE.US', 'XLV.US'
  ],
  individual: [ // 美股个股
    'TM.US', 'NVDA.US', 
    // 'AVGO.US', 'GOOG.US', 'WMT.US', 'JNJ.US', 'META.US', 'GE.US', 'CSCO.US', 'AAPL.US',
    // 'ORCL.US', 'MSFT.US', 'BABA.US', 'ABBV.US', 'TSM.US', 'ABT.US', 'MA.US', 'LIN.US', 'HSBC.US', 'SHEL.US',
    // 'CVX.US', 'MCD.US', 'KO.US', 'HD.US', 'PM.US', 'NVS.US', 'NFLX.US', 'PDD.US', 'COST.US', 'JPM.US',
    // 'AMZN.US', 'SAP.US', 'AZN.US', 'BAC.US', 'WFC.US', 'TSLA.US', 'MSTR.US', 'PEP.US', 'V.US', 'TMO.US',
    // 'IBM.US', 'XOM.US', 'MRK.US', 'BRK.B.US', 'PG.US', 'ASML.US', 'CRM.US', 'LLY.US', 'UNH.US', 'NVO.US', 'ACN.US'
  ]
}

// 响应式数据
const activeTab = ref(1)
const loading = ref(false)
const loadingText = ref('计算中...')
const error = ref('')
const currentStocks = ref([]) // 当前显示的股票数据
const serviceStatus = ref({ status: 'unknown', data: null })
const showServiceStatus = ref(false)
const refreshLoading = ref(false) // 修复数据加载状态

// 排序相关
const sortField = ref('')
const sortOrder = ref('') // 'asc', 'desc', ''

// API基础URL
const API_BASE_URL = '/api'

// 排序函数
const sortBy = (field) => {
  if (sortField.value === field) {
    if (sortOrder.value === 'asc') {
      sortOrder.value = 'desc'
    } else if (sortOrder.value === 'desc') {
      sortOrder.value = ''
      sortField.value = ''
    } else {
      sortOrder.value = 'asc'
    }
  } else {
    sortField.value = field
    sortOrder.value = 'asc'
  }
}

// 排序后的股票列表
const sortedStocks = computed(() => {
  if (!sortField.value || !sortOrder.value) {
    return currentStocks.value
  }
  
  const sorted = [...currentStocks.value].sort((a, b) => {
    let aVal = a[sortField.value]
    let bVal = b[sortField.value]
    
    // 确保数值比较
    if (typeof aVal === 'number' && typeof bVal === 'number') {
      if (sortOrder.value === 'asc') {
        return aVal - bVal
      } else {
        return bVal - aVal
      }
    } else {
      // 字符串比较
      aVal = String(aVal || '')
      bVal = String(bVal || '')
      if (sortOrder.value === 'asc') {
        return aVal.localeCompare(bVal)
      } else {
        return bVal.localeCompare(aVal)
      }
    }
  })
  
  return sorted
})

// 获取恐贪指数颜色类
const getFearGreedClass = (index) => {
  if (index >= 80) return 'extreme-greed'
  if (index >= 50) return 'greed'
  if (index >= 20) return 'slight-greed'
  if (index >= -20) return 'neutral'
  if (index >= -50) return 'fear'
  if (index >= -80) return 'extreme-fear'
  return 'extreme-fear'
}

// 缓存历史数据
const cachedHistoryData = ref({})

// 选择股票
const selectStock = (stock) => {
  // 跳转到股票详情页面
  const stockData = encodeURIComponent(JSON.stringify(stock))
  router.push(`/stock/${stockData}`)
}

// 检查服务状态
const checkServiceStatus = async () => {
  try {
    const response = await fetch(`${API_BASE_URL}/service/status`)
    const data = await response.json()
    
    if (data.success) {
      serviceStatus.value = {
        status: 'healthy',
        data: data.data
      }
    } else {
      serviceStatus.value = {
        status: 'error',
        data: data.error
      }
    }
  } catch (err) {
    serviceStatus.value = {
      status: 'error',
      data: '服务连接失败'
    }
  }
}

// 获取服务状态文本
const getServiceStatusText = () => {
  switch (serviceStatus.value.status) {
    case 'healthy':
      return '服务正常'
    case 'error':
      return '服务异常'
    default:
      return '检查中...'
  }
}

// 重试加载
const retryLoad = () => {
  error.value = ''
  if (activeTab.value === 1) {
    fetchStockData('leverage')
  } else if (activeTab.value === 2) {
    fetchStockData('regular')
  } else if (activeTab.value === 3) {
    fetchStockData('individual')
  }
}

// 获取股票数据
const fetchStockData = async (stockType) => {
  loading.value = true
  error.value = ''
  loadingText.value = `正在获取${getStockTypeText(stockType)}数据...`
  
  try {
    // 根据当前tab获取对应的股票代码数组
    let codes = []
    switch (stockType) {
      case 'leverage':
        codes = STOCK_CODES.leverage
        break
      case 'regular':
        codes = STOCK_CODES.regular
        break
      case 'individual':
        codes = STOCK_CODES.individual
        break
      default:
        codes = []
    }
    
    if (codes.length === 0) {
      throw new Error('未找到对应的股票代码列表')
    }
    
    loadingText.value = `正在计算 ${codes.length} 只股票的恐贪指标...`
    
    // 调用后端API获取股票数据
    const response = await fetch(`${API_BASE_URL}/stocks-data`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        stockType: stockType,
        codes: codes
      })
    })
    
    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status} ${response.statusText}`)
    }
    
    const data = await response.json()
    
    if (data.success) {
      // 更新股票数据
      currentStocks.value = data.data.map(stock => ({
        code: stock.code,
        name: stock.name,
        fearGreedIndex: stock.fearGreedIndex,
        price: stock.price,
        sentiment: stock.sentiment,
        timestamp: stock.timestamp
      }))
      
      console.log(`成功获取 ${data.data.length} 只股票数据`)
    } else {
      throw new Error(data.error || '获取股票数据失败')
    }
  } catch (err) {
    console.error('获取股票数据失败:', err)
    error.value = `获取${getStockTypeText(stockType)}数据失败: ${err.message}`
    currentStocks.value = []
  } finally {
    loading.value = false
    loadingText.value = '计算中...'
  }
}

// 获取股票类型文本
const getStockTypeText = (stockType) => {
  switch (stockType) {
    case 'leverage':
      return '美股杠杆'
    case 'regular':
      return '美股常规'
    case 'individual':
      return '美股个股'
    default:
      return ''
  }
}

// 切换Tab
const switchTab = (index) => {
  activeTab.value = index
  if (index === 1) {
    // 切换到美股杠杆时，自动获取数据
    fetchStockData('leverage')
  } else if (index === 2) {
    // 切换到美股常规时，自动获取数据
    fetchStockData('regular')
  } else if (index === 3) {
    // 切换到美股个股时，自动获取数据
    fetchStockData('individual')
  }
}

// 修复所有数据
const refreshAllData = async () => {
  if (refreshLoading.value) return
  
  refreshLoading.value = true
  error.value = ''
  
  try {
    console.log('🔄 开始修复所有股票数据...')
    
    // 调用修复数据API
    const response = await fetch(`${API_BASE_URL}/stocks/refresh-all-data`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      }
    })
    
    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status} ${response.statusText}`)
    }
    
    const data = await response.json()
    
    if (data.success) {
      console.log('✅ 数据修复成功:', data.message)
      
      // 重新获取当前tab的数据
      if (activeTab.value === 1) {
        await fetchStockData('leverage')
      } else if (activeTab.value === 2) {
        await fetchStockData('regular')
      } else if (activeTab.value === 3) {
        await fetchStockData('individual')
      }
    } else {
      throw new Error(data.error || '数据修复失败')
    }
  } catch (err) {
    console.error('数据修复失败:', err)
    error.value = `数据修复失败: ${err.message}`
  } finally {
    refreshLoading.value = false
  }
}

// 页面加载时检查后端服务并获取数据
onMounted(async () => {
  try {
    // 检查服务健康状态
    const healthResponse = await fetch(`${API_BASE_URL}/health`)
    const healthData = await healthResponse.json()
    console.log('后端服务状态:', healthData)
    
    // 检查服务层状态
    await checkServiceStatus()
    showServiceStatus.value = true
    
    // 如果服务正常，根据当前tab获取数据
    if (healthData.status === 'healthy') {
      if (activeTab.value === 1) {
        fetchStockData('leverage')
      } else if (activeTab.value === 2) {
        fetchStockData('regular')
      } else if (activeTab.value === 3) {
        fetchStockData('individual')
      }
    } else {
      error.value = '后端服务异常，请检查服务状态'
    }
  } catch (err) {
    console.error('后端服务连接失败:', err)
    error.value = '后端服务未启动，请先启动后端服务'
    serviceStatus.value = { status: 'error', data: '服务连接失败' }
    showServiceStatus.value = true
  }
})
</script>

<style scoped>
/* 页面基础样式 */
.indicator-page {
  min-height: 100vh;
  background: #f5f5f5;
  padding: 20px;
}

/* 顶部操作栏样式 */
.action-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding: 16px 20px;
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.action-left .page-title {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: #333;
}

.action-right {
  display: flex;
  gap: 12px;
}

.refresh-btn {
  padding: 10px 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}

.refresh-btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}

.refresh-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

/* Tab容器样式 */
.tab-container {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: row;
  overflow: hidden;
  width: 100%;
  position: relative;
}

.tab-header {
  display: flex;
  background: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
}

.tab-item {
  flex: 1;
  padding: 16px 24px;
  text-align: center;
  cursor: pointer;
  font-size: 16px;
  color: #666;
  border: none;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  transition: all 0.3s ease;
  min-width: 0;
  box-sizing: border-box;
}

.tab-item.active {
  color: #1890ff;
  background: white;
  font-weight: 600;
  border-bottom: 2px solid #1890ff;
}

.tab-item:hover {
  background: #f0f8ff;
  color: #1890ff;
}

.tab-content {
  padding: 20px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .tab-container {
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
  }
  
  .tab-item {
    flex: 0 0 auto;
    min-width: 120px;
    padding: 12px 16px;
    font-size: 14px;
  }
  
  .indicator-page {
    padding: 10px;
  }
  
  .tab-content {
    padding: 10px;
  }
}

.stock-table {
  width: 100%;
  border-collapse: collapse;
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.stock-table th,
.stock-table td {
  padding: 16px 12px;
  text-align: left;
  border-bottom: 1px solid #f0f0f0;
  font-size: 14px;
}

.stock-table th {
  background: #fafafa;
  font-weight: 600;
  color: #333;
}

.stock-table tr:hover {
  background: #f5f5f5;
  cursor: pointer;
}

.stock-code {
  font-weight: 600;
  color: #1890ff;
  font-family: 'Courier New', monospace;
}

.stock-name {
  color: #333;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fear-greed-index span {
  padding: 4px 8px;
  border-radius: 4px;
  font-weight: 600;
  font-size: 12px;
}

.extreme-fear { background: #ff4d4f; color: white; }
.fear { background: #ff7875; color: white; }
.slight-fear { background: #ffa39e; color: white; }
.neutral { background: #faad14; color: white; }
.slight-greed { background: #95de64; color: white; }
.greed { background: #52c41a; color: white; }
.extreme-greed { background: #389e0d; color: white; }

.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #1890ff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 16px;
}

.loading-text {
  color: #666;
  font-size: 14px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 错误状态样式 */
.error-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.error-icon {
  font-size: 48px;
  margin-bottom: 16px;
  color: #ff4d4f;
}

.error-text {
  color: #ff4d4f;
  font-size: 16px;
  text-align: center;
  margin-bottom: 20px;
  max-width: 400px;
  line-height: 1.5;
}

.retry-button {
  background: #1890ff;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.retry-button:hover {
  background: #40a9ff;
}

/* 服务状态指示器 */
.service-status {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 100;
}

.service-indicator {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 20px;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  font-size: 12px;
  font-weight: 500;
}

.service-indicator.healthy {
  color: #52c41a;
  border: 1px solid #b7eb8f;
}

.service-indicator.error {
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

.service-indicator.unknown {
  color: #faad14;
  border: 1px solid #ffe58f;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
  display: inline-block;
}

.service-indicator.healthy .status-dot {
  background: #52c41a;
  animation: pulse 2s infinite;
}

.service-indicator.error .status-dot {
  background: #ff4d4f;
}

.service-indicator.unknown .status-dot {
  background: #faad14;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 1;
  }
}

/* 空状态样式 */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  text-align: center;
}

.empty-icon {
  font-size: 48px;
  margin-bottom: 16px;
  opacity: 0.6;
}

.empty-text {
  font-size: 18px;
  font-weight: 600;
  color: #333;
  margin-bottom: 8px;
}

.empty-desc {
  font-size: 14px;
  color: #666;
}

.sortable-header {
  cursor: pointer;
  user-select: none;
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sort-indicator {
  margin-left: 8px;
}

.sort-arrow {
  font-size: 12px;
  color: #999;
}

.sortable-header:hover .sort-arrow {
  color: #1890ff;
}

</style> 